// cn/iocoder/yudao/module/gold/service/record/GoldMaterialRecordServiceImpl.java
package cn.iocoder.yudao.module.system.service.warehouse;

import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.warehouse.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.warehouse.GoldMaterialRecordDO;
import cn.iocoder.yudao.module.system.dal.dataobject.warehouse.GoldMaterialWarehouseDO;
import cn.iocoder.yudao.module.system.dal.mysql.warehouse.GoldMaterialRecordMapper;
import cn.iocoder.yudao.module.system.dal.mysql.warehouse.GoldMaterialWarehouseMapper;
import cn.iocoder.yudao.module.system.enums.GoldOperationSubTypeEnum;
import cn.iocoder.yudao.module.system.enums.GoldOperationTypeEnum;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;

import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;

@Service
@Validated
public class GoldMaterialRecordServiceImpl implements GoldMaterialRecordService {

    @Resource
    private GoldMaterialWarehouseMapper warehouseMapper;
    @Resource
    private GoldMaterialRecordMapper recordMapper;

    private String genBizNo() {
        return "GM" + IdUtil.getSnowflakeNextIdStr();
    }

    private void assertWarehouse(GoldMaterialWarehouseDO w) {
        if (w == null) throw ServiceExceptionUtil.invalidParamException("仓库不存在");
        if (w.getStatus() != null && w.getStatus() == 0) throw ServiceExceptionUtil.invalidParamException("仓库禁用");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long in(GoldInReqVO reqVO, Long uid, String uname) {
        GoldMaterialWarehouseDO w = warehouseMapper.selectByIdForUpdate(reqVO.getWarehouseId());
        assertWarehouse(w);
        BigDecimal init = w.getBalance() == null ? BigDecimal.ZERO : w.getBalance();
        BigDecimal op = reqVO.getWeight();
        if (warehouseMapper.updateBalanceDelta(w.getId(), op) == 0)
            throw ServiceExceptionUtil.invalidParamException("入库失败");
        BigDecimal fin = init.add(op);
        String no = genBizNo();
        recordMapper.insert(GoldMaterialRecordDO.builder()
                .recordNo(no).warehouseId(w.getId())
                .operationType(GoldOperationTypeEnum.IN.getType())
                .operationSubtype(Integer.valueOf(reqVO.getOperationSubtype()))
                .initialWeight(init).operationWeight(op).finalWeight(fin)
                .operatorId(uid).operatorName(uname).creator(reqVO.getCreator())
                .remark(reqVO.getRemark()).attachmentUrl(reqVO.getAttachmentUrl())
                .businessType(reqVO.getOperationSubtype()).status(1).createTime(LocalDateTime.now()).build());
        return 1L;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long reduce(GoldReduceReqVO reqVO, Long uid, String uname) {
        GoldMaterialWarehouseDO w = warehouseMapper.selectByIdForUpdate(reqVO.getWarehouseId());
        assertWarehouse(w);
        BigDecimal init = w.getBalance();
        BigDecimal op = reqVO.getWeight();
        if (warehouseMapper.updateBalanceDelta(w.getId(), op.negate()) == 0)
            throw ServiceExceptionUtil.invalidParamException("余额不足");
        BigDecimal fin = init.subtract(op);
        String no = genBizNo();
        recordMapper.insert(GoldMaterialRecordDO.builder()
                .recordNo(no).warehouseId(w.getId())
                .operationType(GoldOperationTypeEnum.OUT.getType())
                .operationSubtype(Integer.valueOf(reqVO.getOperationSubtype()))
                .initialWeight(init).operationWeight(op).finalWeight(fin)
                .operatorId(uid).operatorName(uname).creator(reqVO.getCreator())
                .remark(reqVO.getRemark()).attachmentUrl(reqVO.getAttachmentUrl())
                .businessType(reqVO.getOperationSubtype()).status(1).createTime(LocalDateTime.now()).build());
        return 1L;
    }

    @Override
    public PageResult<GoldMaterialRecordDO> getPage(GoldMaterialRecordPageReqVO reqVO) {
        return recordMapper.selectPage(reqVO);
    }

    @Override
    public GoldMaterialRecordStatsRespVO getRecordStats(Long warehouseId) {

        // 查询今日入料总量
        BigDecimal todayIn = recordMapper.selectTodayInTotal(warehouseId);

        // 查询今日出料总量
        BigDecimal todayOut = recordMapper.selectTodayOutTotal(warehouseId);

        // 查询当前余额
        BigDecimal balance = BigDecimal.ZERO;
        if (warehouseId != null) {
            GoldMaterialWarehouseDO warehouse = warehouseMapper.selectById(warehouseId);
            if (warehouse != null) {
                balance = warehouse.getBalance();
            }
        }

        GoldMaterialRecordStatsRespVO stats = new GoldMaterialRecordStatsRespVO();
        stats.setTodayIn(todayIn);
        stats.setTodayOut(todayOut);
        stats.setBalance(balance);

        return stats;
    }

    @Override
    public GoldMaterialGlobalStatsRespVO getGlobalStats() {
        // 查询总金料余额（所有仓库余额之和）
        BigDecimal totalBalance = warehouseMapper.selectTotalBalance();

        // 查询仓库总数量
        Integer warehouseCount = warehouseMapper.selectWarehouseCount();

        // 查询当日进料总克重（所有仓库）
        BigDecimal todayInTotal = recordMapper.selectTodayInTotal(null);

        // 查询当日出料总克重（所有仓库）
        BigDecimal todayOutTotal = recordMapper.selectTodayOutTotal(null);

        // 组装返回数据
        GoldMaterialGlobalStatsRespVO globalStats = new GoldMaterialGlobalStatsRespVO();
        globalStats.setTotalBalance(totalBalance);
        globalStats.setWarehouseCount(warehouseCount);
        globalStats.setTodayInTotal(todayInTotal);
        globalStats.setTodayOutTotal(todayOutTotal);

        return globalStats;
    }
}